/*
 * Copyright (C) 2017 The Android Open Source Project
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package com.xuanyuan.analysis.jetpack;

import android.annotation.SuppressLint;

import androidx.annotation.MainThread;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import androidx.arch.core.executor.ArchTaskExecutor;
import androidx.arch.core.internal.SafeIterableMap;
import androidx.lifecycle.Lifecycle;
import androidx.lifecycle.LifecycleEventObserver;
import androidx.lifecycle.LifecycleOwner;
import androidx.lifecycle.Observer;
import androidx.lifecycle.ViewModel;

import java.util.Iterator;
import java.util.Map;

import static androidx.lifecycle.Lifecycle.State.DESTROYED;
import static androidx.lifecycle.Lifecycle.State.STARTED;

/**
 * LiveData is a data holder class that can be observed within a given lifecycle.
 * LiveData是可以在给定生命周期内观察到的数据持有者类。
 * <p>
 * This means that an {@link Observer} can be added in a pair with a {@link LifecycleOwner}, and
 * this observer will be notified about modifications of the wrapped data only if the paired
 * LifecycleOwner is in active state.
 * 这意味着可以与{@link LifecycleOwner}成对添加一个{@link Observer},
 * 并且仅当配对的LifecycleOwner处于活动状态时，才会向该观察者通知有关包装数据的修改。
 * <p>
 * LifecycleOwner is considered as active, if its state is
 * {@link Lifecycle.State#STARTED} or {@link Lifecycle.State#RESUMED}.
 * 如果LifecycleOwner的状态为{@link Lifecycle #StateSTARTED}或{@link Lifecycle #StateRESUMED}，则将其视为活动状态。
 * <p>
 * An observer added via {@link #observeForever(Observer)} is considered as always active and thus will be always notified
 * about modifications. For those observers, you should manually call {@link #removeObserver(Observer)}.
 * 通过{@link #observeForever（Observer）}添加的观察者被视为始终处于活动状态，因此将始终收到有关修改的通知。
 * 对于那些观察者，您应该手动调用{@link #removeObserver（Observer）}。
 *
 * <p> An observer added with a Lifecycle will be automatically removed if the corresponding
 * Lifecycle moves to {@link Lifecycle.State#DESTROYED} state.
 * 如果相应的生命周期变为{@link Lifecycle #StateDESTROYED}状态，则添加了生命周期的观察者将被自动删除。
 * <p>
 * This is especially useful for activities and fragments where they can safely observe LiveData and not worry about leaks:
 * they will be instantly unsubscribed when they are destroyed.
 * 这对于活动和片段可以安全地观察LiveData而不用担心泄漏的活动特别有用：销毁它们时，它们将立即被取消订阅。
 * <p>
 * In addition, LiveData has {@link LiveData#onActive()} and {@link LiveData#onInactive()} methods
 * to get notified when number of active {@link Observer}s change between 0 and 1.
 * 此外，LiveData具有{@link LiveData onActive（）}和{@link LiveData onInactive（）}方法，可在活动{@link Observer}的数量在0到1之间变化时得到通知。
 * <p>
 * This allows LiveData to release any heavy resources when it does not have any Observers that
 * are actively observing.
 * 当LiveData没有actively的观察者时，这使LiveData可以释放任何繁重的资源
 * <p>
 * This class is designed to hold individual data fields of {@link ViewModel},
 * but can also be used for sharing data between different modules in your application in a decoupled fashion.
 * 此类旨在容纳{@link ViewModel}的各个数据字段，
 * 但也可以用于以分离的方式在应用程序中的不同模块之间共享数据。
 *
 * @param <T> The type of data held by this instance 此实例保存的数据类型
 * @see ViewModel
 */
@SuppressLint("RestrictedApi")
public class LiveData<T> {
    @SuppressWarnings("WeakerAccess") /* synthetic access */
    final Object mDataLock = new Object();
    /**
     * 每个数据变化的版本,数据修改变动一次,START_VERSION就会自增1
     */
    static final int START_VERSION = -1;
    @SuppressWarnings("WeakerAccess") /* synthetic access */
    static final Object NOT_SET = new Object();

    @SuppressLint("RestrictedApi")
    private SafeIterableMap<Observer<? super T>, ObserverWrapper> mObservers = new SafeIterableMap<>();

    // how many observers are in active state
    @SuppressWarnings("WeakerAccess") /* synthetic access */
            int mActiveCount = 0;
    private volatile Object mData = NOT_SET;
    // when setData is called, we set the pending data and actual data swap happens on the main thread
    // 调用setData时，我们设置待处理数据，实际数据交换发生在主线程上
    @SuppressWarnings("WeakerAccess") /* synthetic access */
    volatile Object mPendingData = NOT_SET;
    private int mVersion = START_VERSION;

    private boolean mDispatchingValue;
    @SuppressWarnings("FieldCanBeLocal")
    private boolean mDispatchInvalidated;

    private final Runnable mPostValueRunnable = () -> {
        Object newValue;
        synchronized (mDataLock) {
            newValue = mPendingData;
            mPendingData = NOT_SET;
        }
        //noinspection unchecked
        setValue((T) newValue);
    };

    /**
     * Check latest state b4 dispatch. Maybe it changed state but we didn't get the event yet.
     * 检查最新状态b4调度。也许它改变了状态，但是我们还没有得到这个事件。
     * <p>
     * we still first check observer.active to keep it as the entrance for events.
     * 我们仍然要先检查observer.active，以确保它是事件的入口。
     * So even if the observer moved to an active state, if we've not received that event,
     * 因此，即使观察者变为活动状态，如果我们尚未收到该事件
     * we better not notify for a more predictable notification order.
     * 我们最好不要通知更可预测的通知顺序
     * <p>
     * 执行数据刷新操作
     */
    private void considerNotify(ObserverWrapper observer) {
        //确保ObserverWrapper是mActive=ture才能继续执行
        if (!observer.mActive) {
            return;
        }
        //确保当前生命周期处于允许状态，可继续执行后续代码
        if (!observer.shouldBeActive()) {
            observer.activeStateChanged(false);
            return;
        }

        //数据未发射处理过方可进行后续操作
        if (observer.mLastVersion >= mVersion) {
            return;
        }
        observer.mLastVersion = mVersion;
        //进行数据刷新
        observer.mObserver.onChanged((T) mData);
    }

    @SuppressWarnings("WeakerAccess") /* synthetic access */
    void dispatchingValue(@Nullable ObserverWrapper initiator) {
        if (mDispatchingValue) {
            //如果正在进行数据的分发则此次分发无效
            mDispatchInvalidated = true;
            return;
        }
        mDispatchingValue = true;
        do {
            mDispatchInvalidated = false;
            if (initiator != null) {
                considerNotify(initiator);
                initiator = null;
            } else {
                for (Iterator<Map.Entry<Observer<? super T>, ObserverWrapper>> iterator =
                     mObservers.iteratorWithAdditions(); iterator.hasNext(); ) {
                    considerNotify(iterator.next().getValue());
                    if (mDispatchInvalidated) {
                        break;
                    }
                }
            }
        } while (mDispatchInvalidated);
        mDispatchingValue = false;
    }

    /**
     * Adds the given observer to the observers list within the lifespan of the given
     * owner. The events are dispatched on the main thread. If LiveData already has data
     * set, it will be delivered to the observer.
     * <p>
     * 将给定的观察者添加到给定所有者的生存期内的观察者列表中。事件在主线程上调度。
     * 如果LiveData已经设置了数据，它将被传递给观察者。
     * <p>
     * The observer will only receive events if the owner is in {@link Lifecycle.State#STARTED}
     * or {@link Lifecycle.State#RESUMED} state (active).
     * 仅当所有者处于{@link Lifecycle #StateSTARTED}或{@link Lifecycle #StateRESUMED}状态（活动）时，观察者才会收到事件。
     *
     * <p>
     * If the owner moves to the {@link Lifecycle.State#DESTROYED} state, the observer will
     * automatically be removed.
     * 如果所有者移至{@link Lifecycle #StateDESTROYED}状态，则观察者将被自动删除。
     * <p>
     * When data changes while the {@code owner} is not active, it will not receive any updates.
     * If it becomes active again, it will receive the last available data automatically.
     * 在{@code owner}未激活的情况下更改数据时，它将不会收到任何更新。如果再次激活，它将自动接收最新的可用数据。
     * <p>
     * LiveData keeps a strong reference to the observer and the owner as long as the
     * given LifecycleOwner is not destroyed. When it is destroyed, LiveData removes references to
     * the observer &amp; the owner.
     * 只要不破坏给定的LifecycleOwner，LiveData就会对观察者和所有者保持强烈的引用。
     * 销毁后，LiveData会删除对观察者和所有者的引用。
     * <p>
     * If the given owner is already in {@link Lifecycle.State#DESTROYED} state, LiveData
     * ignores the call.
     * 如果给定的所有者已经处于{@link Lifecycle #StateDESTROYED}状态，则LiveData将忽略该调用。
     * <p>
     * If the given owner, observer tuple is already in the list, the call is ignored.
     * 如果给定的所有者,observer元组已经在列表中，则该调用将被忽略。
     * If the observer is already in the list with another owner, LiveData throws an
     * {@link IllegalArgumentException}.
     * 如果观察者已经在列表中且具有另一个所有者，则LiveData会引发{@link IllegalArgumentException}。
     *
     * @param owner    The LifecycleOwner which controls the observer   控制观察者的LifecycleOwner
     * @param observer The observer that will receive the events    将接收事件的观察者
     */
    @MainThread
    public void observe(@NonNull LifecycleOwner owner, @NonNull Observer<? super T> observer) {
        // 判断是否在主线程，不在则抛异常
        assertMainThread("observe");
        // owner处于DESTROYED状态则无法进行Observer注册
        if (owner.getLifecycle().getCurrentState() == DESTROYED) {
            // ignore
            return;
        }
        LifecycleBoundObserver wrapper = new LifecycleBoundObserver(owner, observer);
        // 从mObservers中获取LiveData.ObserverWrapper，如果不存在则返回null
        ObserverWrapper existing = mObservers.putIfAbsent(observer, wrapper);
        //如果Observer被注册过，但是owner前后不一致，则抛异常。
        if (existing != null && !existing.isAttachedTo(owner)) {
            throw new IllegalArgumentException("Cannot add the same observer"
                    + " with different lifecycles");
        }
        if (existing != null) {
            return;
        }
        //将wrapper加入observer的观察者列表
        owner.getLifecycle().addObserver(wrapper);
    }

    /**
     * Adds the given observer to the observers list. This call is similar to
     * {@link LiveData#observe(LifecycleOwner, Observer)} with a LifecycleOwner, which is always active.
     * 将给定的观察者添加到观察者列表中。此调用类似于带有生命周期所有者的{@link LiveData observe（LifecycleOwner，Observer）}，该生命周期所有者始终处于活动状态。
     * <p>
     * This means that the given observer will receive all events and will never be automatically removed.
     * 这意味着给定的观察者将接收所有事件，并且永远不会被自动删除。
     * <p>
     * You should manually call {@link #removeObserver(Observer)} to stop observing this LiveData.
     * 您应该手动调用{@link #removeObserver（Observer）}以停止观察此LiveData。
     * <p>
     * While LiveData has one of such observers, it will be considered as active.
     * 当LiveData具有此类观察者之一，但它将被视为active。
     *
     * <p>
     * If the observer was already added with an owner to this LiveData, LiveData throws an
     * {@link IllegalArgumentException}.
     * 如果已将观察者和所有者添加到此LiveData，则LiveData会引发{@link IllegalArgumentException}。
     *
     * @param observer The observer that will receive the events 将接收事件的观察者
     */
    @MainThread
    public void observeForever(@NonNull Observer<? super T> observer) {
        //是否在主线程中
        assertMainThread("observeForever");
        AlwaysActiveObserver wrapper = new AlwaysActiveObserver(observer);
        //判断是否已在mObservers列表中
        ObserverWrapper existing = mObservers.putIfAbsent(observer, wrapper);
        // 如果在此之前已将观察者和所有者绑定的ObserverWrapper添加进入LiveData，则抛IllegalArgumentException
        if (existing != null && existing instanceof LiveData.LifecycleBoundObserver) {
            throw new IllegalArgumentException("Cannot add the same observer"
                    + " with different lifecycles");
        }
        if (existing != null) {
            return;
        }
        //设置wrapper更新为active=true
        wrapper.activeStateChanged(true);
    }

    /**
     * Removes the given observer from the observers list.
     * 从观察者列表中删除给定的观察者
     *
     * @param observer The Observer to receive events.
     */
    @MainThread
    public void removeObserver(@NonNull final Observer<? super T> observer) {
        assertMainThread("removeObserver");
        ObserverWrapper removed = mObservers.remove(observer);
        //observer原本就不存在于mObservers中
        if (removed == null) {
            return;
        }
        //如果ObserverWrapper含有owner,则将observer从owner的观察者列表中移除
        removed.detachObserver();
        //设置ObserverWrapper的active=false,状态改变为非激活状态
        removed.activeStateChanged(false);
    }

    /**
     * Removes all observers that are tied to the given {@link LifecycleOwner}.
     * 删除与给定的{@link LifecycleOwner}关联的所有观察者。
     *
     * @param owner The {@code LifecycleOwner} scope for the observers to be removed.
     */
    @SuppressWarnings("WeakerAccess")
    @MainThread
    public void removeObservers(@NonNull final LifecycleOwner owner) {
        assertMainThread("removeObservers");
        for (Map.Entry<Observer<? super T>, ObserverWrapper> entry : mObservers) {
            if (entry.getValue().isAttachedTo(owner)) {
                removeObserver(entry.getKey());
            }
        }
    }

    /**
     * Posts a task to a main thread to set the given value. So if you have a following code
     * executed in the main thread:
     * 将任务发布到主线程以设置给定值。因此，如果您在主线程中执行了以下代码：
     * <pre class="prettyprint">
     * liveData.postValue("a");
     * liveData.setValue("b");
     * </pre>
     * The value "b" would be set at first and later the main thread would override it with
     * the value "a".
     * 首先将设置值“ b”，然后主线程将使用值“ a”覆盖它。
     * <p>
     * If you called this method multiple times before a main thread executed a posted task, only
     * the last value would be dispatched.
     * 如果在主线程执行发布的任务之前多次调用此方法，则只会分派最后一个值。
     *
     * @param value The new value
     */

    protected void postValue(T value) {
        boolean postTask;
        synchronized (mDataLock) {
            // true：上一个数据已发送完毕，处于就绪状态
            postTask = mPendingData == NOT_SET;
            mPendingData = value;
        }
        if (!postTask) {
            //上一个数据还未发送完毕,不可发布
            return;
        }
        //在主线程中执行发布任务，修改设置
        ArchTaskExecutor.getInstance().postToMainThread(mPostValueRunnable);
    }

    /**
     * Sets the value. If there are active observers, the value will be dispatched to them.
     * 设置值。如果有活动的观察者，那么值将分派给他们。
     * <p>
     * This method must be called from the main thread. If you need set a value from a background
     * thread, you can use {@link #postValue(Object)}
     * 必须从主线程调用此方法。如果需要从后台线程设置值，则可以使用{@link #postValue(Object)}
     *
     * @param value The new value
     */
    @MainThread
    protected void setValue(T value) {
        assertMainThread("setValue");
        //修改mVersion，标识每个value
        mVersion++;
        mData = value;
        dispatchingValue(null);
    }

    /**
     * Returns the current value.
     * Note that calling this method on a background thread does not guarantee that the latest
     * value set will be received.
     * 返回当前值。请注意，在后台线程上调用此方法不能保证将接收到最新的值集。
     *
     * @return the current value
     */
    @Nullable
    public T getValue() {
        Object data = mData;
        if (data != NOT_SET) {
            //noinspection unchecked
            return (T) data;
        }
        return null;
    }

    int getVersion() {
        return mVersion;
    }

    /**
     * Called when the number of active observers change to 1 from 0.
     * 当活动观察者的数量从0变为1时调用
     * <p>
     * This callback can be used to know that this LiveData is being used thus should be kept
     * up to date.
     * 此回调可用于知道正在使用此LiveData，因此应保持最新状态
     */
    protected void onActive() {

    }

    /**
     * Called when the number of active observers change from 1 to 0.
     * <p>当活动观察者的数量从1变为0时调用。
     * This does not mean that there are no observers left, there may still be observers but their
     * lifecycle states aren't {@link Lifecycle.State#STARTED} or {@link Lifecycle.State#RESUMED}
     * (like an Activity in the back stack).
     * 这并不意味着没有观察者，可能仍然有观察者，
     * 但是它们的生命周期状态不是{@link Lifecycle #StateSTARTED}或{@link Lifecycle #StateRESUMED}
     * <p>
     * You can check if there are observers via {@link #hasObservers()}.
     * 您可以通过以下方式检查是否有观察员
     */
    protected void onInactive() {

    }

    /**
     * Returns true if this LiveData has observers.
     *
     * @return true if this LiveData has observers
     */
    @SuppressWarnings("WeakerAccess")
    public boolean hasObservers() {
        return mObservers.size() > 0;
    }

    /**
     * Returns true if this LiveData has active observers.
     *
     * @return true if this LiveData has active observers
     */
    @SuppressWarnings("WeakerAccess")
    public boolean hasActiveObservers() {
        return mActiveCount > 0;
    }

    /**
     * 生命周期约束Observer
     */
    class LifecycleBoundObserver extends ObserverWrapper implements LifecycleEventObserver {
        @NonNull
        final LifecycleOwner mOwner;

        LifecycleBoundObserver(@NonNull LifecycleOwner owner, Observer<? super T> observer) {
            super(observer);
            mOwner = owner;
        }

        /**
         * 确定Observer在处于STARDED和RESUMED状态时,处于活动状态
         */
        @Override
        boolean shouldBeActive() {
            return mOwner.getLifecycle().getCurrentState().isAtLeast(STARTED);
        }

        /**
         * 相较父类的方法多了一层判断,当mOwner处于DESTROYED状态时自动将Observer从LiveData的观察者列表mObservers中移除
         */
        @Override
        public void onStateChanged(LifecycleOwner source, Lifecycle.Event event) {
            if (mOwner.getLifecycle().getCurrentState() == DESTROYED) {
                removeObserver(mObserver);
                return;
            }
            activeStateChanged(shouldBeActive());
        }

        @Override
        boolean isAttachedTo(LifecycleOwner owner) {
            return mOwner == owner;
        }

        /**
         * 移除在mOwner观察列表中的LifecycleBoundObserver
         */
        @Override
        void detachObserver() {
            mOwner.getLifecycle().removeObserver(this);
        }

    }

    /**
     * Observer包装类
     */
    private abstract class ObserverWrapper {
        //每个包装类都含有一个Observer
        final Observer<? super T> mObserver;
        // Observer活动状态active标识，只有处于活动状态的Observer，才能发射数据
        boolean mActive;
        // Observer的version标识
        int mLastVersion = START_VERSION;

        ObserverWrapper(Observer<? super T> observer) {
            mObserver = observer;
        }

        //是否应该处于Active
        abstract boolean shouldBeActive();

        /**
         * 是否Attached了owner
         */
        boolean isAttachedTo(LifecycleOwner owner) {
            return false;
        }

        /**
         * 分离owner，需要子类中重写
         */
        void detachObserver() {
        }

        /**
         * active 激活状态的更改,条件达到会调用LiveData的onActive()和onInactive()方法
         * 1.当newActive=true时,LiveData中的活跃数量mActiveCount由0变为1时，调用onActive()，同时发布值dispatchingValue(this)
         * 2.当newActive=false时,LiveData中的活跃数量mActiveCount由1变为0时,调用onInactive()
         */
        void activeStateChanged(boolean newActive) {
            if (newActive == mActive) {
                return;
            }
            // immediately set active state, so we'd never dispatch anything to inactive
            // owner
            mActive = newActive;
            boolean wasInactive = LiveData.this.mActiveCount == 0;
            LiveData.this.mActiveCount += mActive ? 1 : -1;
            if (wasInactive && mActive) {
                onActive();
            }
            if (LiveData.this.mActiveCount == 0 && !mActive) {
                onInactive();
            }
            if (mActive) {
                dispatchingValue(this);
            }
        }
    }

    /**
     * 总是处于活跃状态的 Observer包装类
     */
    private class AlwaysActiveObserver extends ObserverWrapper {
        AlwaysActiveObserver(Observer<? super T> observer) {
            super(observer);
        }

        @Override
        boolean shouldBeActive() {
            return true;
        }
    }

    /***
     * 断言 方法X是否运行在主线程中
     * @param methodName 方法名
     */
    private static void assertMainThread(String methodName) {
        if (!ArchTaskExecutor.getInstance().isMainThread()) {
            throw new IllegalStateException("Cannot invoke " + methodName + " on a background"
                    + " thread");
        }
    }
}
